Add Japanese localization of Academy at /academy/japan/#3018
Add Japanese localization of Academy at /academy/japan/#3018kurosawa-gao wants to merge 2 commits into
Conversation
- Localize Academy pages: Tracing, Monitoring + Error Analysis, Datasets, Experiments, Evaluation, AI Engineering Loop. - Add index page and meta.json for the Japanese section. - Add a FAQ entry on the /japan LP linking to the Japanese Academy. - Add a "Translation by GAO, Inc." credit (visible link) on each Japanese Academy page. - TSX components (LoopDiagram, ManualGuideList, etc.) accept a `locale` prop and render Japanese strings when locale="ja".
|
@kurosawa-gao is attempting to deploy a commit to the langfuse Team on Vercel. A member of the Team first needs to authorize it. |
|
|
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
|
Regarding the untranslated labels noted by greptile-apps:
|
|
@claude review |
There was a problem hiding this comment.
This is a large content PR (29 files, XXL) adding Japanese Academy localization — code-side changes look clean and additive (optional locale props on Academy components default to English, the new japan collection is isolated from the existing academy collection, and the route-group rename to app/academy/(en)/ is URL-transparent), but the Japanese translation quality and the user-facing decisions (intentional English labels for "Session/Trace/Observation" and "Step 01/02/03", GAO attribution placement) are worth a human signoff.
Extended reasoning...
Overview
This PR adds a Japanese localization of the Langfuse Academy at /academy/japan/ via:
- A new Fumadocs collection (
academyJa) loaded fromcontent/academy/japan/, separate from the Englishacademycollection (which now excludesjapan/**). - Route restructure:
app/academy→app/academy/(en)(URL-transparent route group) plus a newapp/academy/japan/[[...slug]]/route. - 8 new Japanese MDX pages (Tracing, Monitoring + Error Analysis, Datasets, Experiments, Evaluation, AI Engineering Loop, index).
- Optional
localeprop threaded through 9 Academy TSX components (LoopDiagram,LoopSubset,ManualGuideCallout,AgentPromptCallout, and several diagram components) that render Japanese strings whenlocale="ja"and English otherwise. - A new
bottomSuffixslot onDocsChromePagefor the "Translation by GAO, Inc." attribution. - A FAQ entry on the
/japanlanding page linking to the Japanese Academy.
Security risks
Minimal. The only external link added (gao-ai.com attribution) was flagged by Greptile for missing noreferrer; the PR was opened with rel="noopener noreferrer" already in place. No auth/permissions/crypto code is touched.
Level of scrutiny
Medium. The TS/code surface area is small and additive — locale is optional everywhere and defaults preserve existing English rendering, so the English Academy is unaffected. The route-group rename is a no-op for URLs but worth verifying that breadcrumbs/canonicals still resolve. The bulk of the diff is Japanese content, which deserves a native-speaker / domain review for terminology consistency (especially the intentional English-vs-Japanese label decisions the author called out: Session/Trace/Observation kept in English to match the Langfuse UI; "Step 01/02/03" kept as decorative numerals).
Other factors
- The author actively engaged with the Greptile review and provided a clear rationale for the intentional untranslated labels.
- Two minor nits flagged by the bug hunter (inline): a dead
locale="ja"prop onManualGuideListand aSTEPS.lengthvssteps.lengthinconsistency inErrorAnalysisProcessDiagram. Both are cosmetic and have no user-visible defect today. - The PR is labeled
size:XXL(29 files) and adds a third-party attribution (GAO, Inc.) that the author explicitly flagged as not previously discussed — that's a small editorial/branding decision worth a maintainer call.
| <ManualGuideList | ||
| locale="ja" |
There was a problem hiding this comment.
🟡 <ManualGuideList locale="ja" title="その他のガイド" guides={...}/> passes a locale="ja" prop, but ManualGuideList only accepts { title?, guides } — React silently drops the unknown prop. It's currently harmless because title is explicitly overridden, but it's misleading dead code that pattern-matches the other locale-aware Academy components in this PR (LoopDiagram, ManualGuideCallout, EvaluationEvolutionDiagram, etc.). Either drop the locale prop from the call site or extend ManualGuideList to accept it for consistency.
Extended reasoning...
What the bug is
In content/academy/japan/evaluate.mdx (lines 197–222), the call site renders:
<ManualGuideList
locale="ja"
title="その他のガイド"
guides={[ ... ]}
/>But components/academy/ManualGuideList.tsx defines its props as { title?: string; guides: ManualGuideListItem[] } and its body destructures only { title = "Guides", guides }. React silently ignores unknown props on functional/non-DOM components, so locale="ja" is dead code — it never reaches any rendering logic.
Why it doesn't blow up today
The component currently has nothing locale-dependent that the caller doesn't already control:
titleis explicitly overridden to"その他のガイド", so the default English"Guides"never appears.- Each
GuideRowrenders caller-providedtopic/ledestrings verbatim — those are already Japanese in theguidesarray.
So visually the output is identical with or without locale="ja". Functional impact today: zero.
Why it still matters
This PR threads a locale prop through nine other Academy components (LoopDiagram, ManualGuideCallout, AgentPromptCallout, DatasetFieldsDiagram, ErrorAnalysisProcessDiagram, EvaluationEvolutionDiagram, LoopSubset, RagTraceViewDiagram, TracingHierarchyDiagram) — and in all of those the prop actually does something. A reader scanning this MDX would reasonably assume locale="ja" here also has effect, and a future contributor adding a localizable string to ManualGuideList (e.g. a default "More guides" ribbon) would silently inherit a broken locale wire-up.
Step-by-step proof
- Author writes
<ManualGuideList locale="ja" title="その他のガイド" guides={...}/>inevaluate.mdx. - MDX compiles this to
React.createElement(ManualGuideList, { locale: "ja", title: "その他のガイド", guides: [...] }). ManualGuideListis defined asfunction ManualGuideList({ title = "Guides", guides }: ManualGuideListProps)— onlytitleandguidesare destructured.- JavaScript destructuring ignores any extra keys on the props object, so
localeis never read. ManualGuideListdoes not spread...restonto a DOM node or pass props through anywhere, so React never warns about an unknown DOM attribute either.- The component renders identically whether
locale="ja"is present or absent.
How to fix
Two equally valid options, depending on whether ManualGuideList is expected to grow locale-aware strings later:
- Drop the prop (smallest change): remove
locale="ja"from the MDX call site inevaluate.mdx.titleis already explicitly localized. - Extend the component (matches the rest of the PR): add
locale?: stringtoManualGuideListProps, destructure it, and use it for the default ribbon label (e.g.title = locale === "ja" ? "ガイド" : "Guides") — mirroring howManualGuideCalloutlocalizes itsribbonPrefixandctaText.
Severity: nit — cleanup/consistency, no current user-visible defect.
| style={{ transform: `scale(${estScale})` }} | ||
| > | ||
| {STEPS.map((step, i) => ( | ||
| {steps.map((step, i) => ( |
There was a problem hiding this comment.
🟡 The .map at line 105 iterates the locale-aware steps array, but the connector guard at line 120 still references STEPS.length (the English-only constant). Both STEPS and STEPS_JA happen to have 5 entries today, so there is no user-visible defect, but a future contributor adding or removing a step from one array only would render an orphan connector or miss one. One-line fix: STEPS.length → steps.length.
Extended reasoning...
What the bug is. This PR introduces a locale-aware steps array (const steps = locale === "ja" ? STEPS_JA : STEPS) and correctly switches the .map call at line 105 from STEPS.map to steps.map. However, the connector guard immediately below at line 120 still reads {i < STEPS.length - 1 && ...}, referencing the English-only STEPS constant rather than the locale-selected steps array.
Why it's latent today. STEPS and STEPS_JA each contain exactly 5 entries, so STEPS.length === steps.length for every supported locale and the rendered output is identical to using steps.length. No user will see a visual defect on this PR as it stands — this is purely a code-quality / consistency issue.
Why it still matters. The diff introduced steps precisely to abstract over locale, and one of the two sites that needs it was missed. The inconsistency is a footgun for future contributors: if someone adds or removes a step from STEPS_JA (or adds a third locale array, e.g. STEPS_DE) and forgets to make a matching edit to STEPS, the connector count will no longer match the rendered step count — producing either an orphan trailing connector or a missing connector between the last two cards.
Step-by-step proof. Suppose a future contributor adds a 6th step to STEPS_JA:
steps = STEPS_JAnow has length 6.- The
.mapat line 105 renders 6 step cards (indices i=0..5). - The guard at line 120 evaluates
i < STEPS.length - 1, i.e.i < 4(becauseSTEPS.lengthis still 5). - Connectors are rendered for i=0,1,2,3 — only 4 connectors between 6 cards.
- The 5th and 6th cards have no connector between them. Conversely, if a step is removed from
STEPSwhileSTEPS_JAkeeps 5, an extra connector renders past the last card.
How to fix. Change STEPS.length to steps.length on line 120 so the guard derives from the same array being iterated. This is the same one-line change Greptile-style reviewers would call out — defensive, consistent with the abstraction the diff introduced.
Motivation
The Langfuse Academy is a strong introduction to AI engineering and
LLMOps fundamentals — content that's especially valuable for teams
new to LLM observability. A Japanese translation makes this learning
path accessible to Japanese developers and lowers the barrier to
applying the practices it covers.
Summary
/academy/japan/.Evaluation, and the AI Engineering Loop overview.
/japanlanding page that links tothe Japanese Academy.
LoopDiagram,ManualGuideCallout,diagram components, etc.) accept an optional
localeprop and renderJapanese strings when
locale="ja". Without the prop they renderunchanged, so existing English pages are unaffected by default.
Context
@kamonspecial reached out offering to contribute a Japanese
translation, and @clemra agreed to the proposed
/academy/japan/path as a starting point. Any future URL adjustments will be on
Langfuse as the broader internationalization approach takes shape.
A small "Translation by GAO, Inc." credit appears at the bottom of
each Japanese page. This wasn't part of the earlier discussion, so
happy to remove or change it if preferred.
One figure (
experimentation.png) is left in English; this can berevisited once Figma source coordination is possible.
Test plan
spot-check on
/academy/japan/tracing).#user-feedback) work as expected.app/academy → app/academy/(en)route group rename (verified/academyand/academy/tracingvisually).Thanks for considering — happy to address any feedback.
🤖 Generated with Claude Code
Greptile Summary
This PR adds a full Japanese localization of the Langfuse Academy at
/academy/japan/, implemented as a standalone Fumadocs collection rather than the built-in i18n layer, so the new URLs live naturally under/academy/japan/without a locale prefix.(en)route group (URL-transparent) and its Fumadocs collection now excludesjapan/**so there is no overlap.localeprop and render Japanese strings whenlocale=\"ja\"; existing English pages are unaffected.bottomSuffixslot is added toDocsChromePageto render the "Translation by GAO, Inc." attribution, and the/japanlanding page gains a FAQ entry linking to the new Japanese Academy.Confidence Score: 4/5
Safe to merge. The English academy is unaffected by the route-group rename, the collection exclusion patterns are correct, and all new locale-aware component props are optional with backwards-compatible defaults.
The change is well-scoped: new content files, a parallel Fumadocs collection, and additive locale props on existing components. The only findings are cosmetic — a missing
noreferreron one external link and a handful of diagram labels left in English for the Japanese locale, which may be intentional for technical-term consistency with the Langfuse UI.app/academy/japan/[[...slug]]/page.tsxfor the attribution link'srelattribute;components/academy/TracingHierarchyDiagram.tsxandcomponents/academy/EvaluationEvolutionDiagram.tsxfor the untranslated visible labels.Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A["Request: /academy/japan/[...slug]"] --> B["app/academy/japan/[[...slug]]/page.tsx"] C["Request: /academy/[...slug]"] --> D["app/academy/(en)/[[...slug]]/page.tsx"] B --> E["academyJaSource.getPage(slug)"] D --> F["academySource.getPage(slug)"] E --> G["content/academy/japan/**/*.mdx\n(academyJa collection)"] F --> H["content/academy/**/*.mdx\n(excludes japan/**)"] B --> I["DocsChromePage + bottomSuffix (GAO attribution)"] D --> J["DocsChromePage (no suffix)"] I --> M["Locale-aware components\ne.g. LoopDiagram locale='ja'"]Prompt To Fix All With AI
Reviews (1): Last reviewed commit: "feat(academy): Japanese localization at ..." | Re-trigger Greptile